#include "../../Drivers/BSP/sterper/sterper.h"
a
/* 定时器句柄 */
TIM_HandleTypeDef TIM_StepperHandle;

/* 步进电机数组 */
Stepper_TypeDef step_motor[3] =
{
    {X_MOTOR_PUL_PIN, X_MOTOR_DIR_PIN, X_MOTOR_PUL_CHANNEL, X_MOTOR_PUL_PORT, X_MOTOR_DIR_GPIO_PORT},
    {Y_MOTOR_PUL_PIN, Y_MOTOR_DIR_PIN, Y_MOTOR_PUL_CHANNEL, Y_MOTOR_PUL_PORT, Y_MOTOR_DIR_GPIO_PORT},
    {Z_MOTOR_PUL_PIN, Z_MOTOR_DIR_PIN, Z_MOTOR_PUL_CHANNEL, Z_MOTOR_PUL_PORT, Z_MOTOR_DIR_GPIO_PORT},
};

/**
  * @brief  中断优先级配置
  * @param  无
  * @retval 无
  */
static void TIMx_NVIC_Configuration(void)
{
    /* 外设中断配置 */
    HAL_NVIC_SetPriority(MOTOR_PUL_IRQn, 0, 1);
    HAL_NVIC_EnableIRQ(MOTOR_PUL_IRQn);
}

/**
  * @brief  配置TIM复用输出PWM时用到的I/O
  * @param  无
  * @retval 无
  */
static void Stepper_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    X_MOTOR_DIR_GPIO_CLK_ENABLE();
    X_MOTOR_PUL_GPIO_CLK_ENABLE();

    Y_MOTOR_DIR_GPIO_CLK_ENABLE();
    Y_MOTOR_PUL_GPIO_CLK_ENABLE();

    Z_MOTOR_DIR_GPIO_CLK_ENABLE();
    Z_MOTOR_PUL_GPIO_CLK_ENABLE();
    /* 获取数组元素个数 */
    uint8_t member_count = sizeof(step_motor) / sizeof(Stepper_TypeDef);

    for(uint8_t i = 0; i < member_count; i++)
    {
        /*选择要控制的GPIO引脚*/
        GPIO_InitStruct.Pin = step_motor[i].dir_pin;
        /*设置引脚的输出类型为推挽输出*/
        GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        /*设置引脚速率为高速 */
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        /*Motor 方向引脚 初始化*/
        HAL_GPIO_Init(step_motor[i].dir_port, &GPIO_InitStruct);
        MOTOR_DIR(step_motor[i].dir_port, step_motor[i].dir_pin, CW);


        /* 定时器输出通道功能引脚IO初始化 */
        /*设置输出类型*/
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        /*设置引脚速率 */
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        /*设置复用*/
        GPIO_InitStruct.Alternate = MOTOR_PUL_GPIO_AF;
        /*设置复用*/
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        /*选择要控制的GPIO引脚*/
        GPIO_InitStruct.Pin = step_motor[i].pul_pin;
        /*Motor 脉冲引脚 初始化*/
        HAL_GPIO_Init(step_motor[i].pul_port, &GPIO_InitStruct);
        MOTOR_PUL(step_motor[i].pul_port, step_motor[i].pul_pin, LOW);
    }
}

static void TIM_PWMOUTPUT_Config(void)
{
    TIM_OC_InitTypeDef  TIM_OCInitStructure;

    /* 获取数组元素个数 */
    uint8_t member_count = sizeof(step_motor) / sizeof(Stepper_TypeDef);

    /*使能定时器*/
    MOTOR_PUL_CLK_ENABLE();

    TIM_StepperHandle.Instance = MOTOR_PUL_TIM;
    /* 累计 TIM_Period个后产生一个更新或者中断*/
    //当定时器从0计数到TIM_PERIOD，即为TIM_PERIOD次，为一个定时周期
    TIM_StepperHandle.Init.Period = TIM_PERIOD;
    // 通用控制定时器时钟源TIMxCLK = HCLK=168MHz
    // 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=2MHz
    TIM_StepperHandle.Init.Prescaler = TIM_PRESCALER - 1;

    /*计数方式*/
    TIM_StepperHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
    /*采样时钟分频*/
    TIM_StepperHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    TIM_StepperHandle.Init.RepetitionCounter = 0 ;
    /*初始化定时器*/
    HAL_TIM_OC_Init(&TIM_StepperHandle);

    /*PWM模式配置--这里配置为输出比较模式*/
    TIM_OCInitStructure.OCMode = TIM_OCMODE_PWM2;
    /*比较输出的计数值*/
    TIM_OCInitStructure.Pulse = TIM_PERIOD;
    /*当定时器计数值小于CCR1_Val时为高电平*/
    TIM_OCInitStructure.OCPolarity = TIM_OCPOLARITY_HIGH;
    /*设置互补通道输出的极性*/
    TIM_OCInitStructure.OCNPolarity = TIM_OCNPOLARITY_HIGH;
    /*快速模式设置*/
    TIM_OCInitStructure.OCFastMode = TIM_OCFAST_DISABLE;
    /*空闲电平*/
    TIM_OCInitStructure.OCIdleState = TIM_OCIDLESTATE_RESET;
    /*互补通道设置*/
    TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET;

    for(uint8_t i = 0; i < member_count; i++)
    {
        /* 启动比较输出并使能中断 */
        HAL_TIM_OC_ConfigChannel(&TIM_StepperHandle, &TIM_OCInitStructure, step_motor[i].pul_channel);
        TIM_CCxChannelCmd(MOTOR_PUL_TIM, step_motor[i].pul_channel, TIM_CCx_DISABLE);
    }
}


/**
  * @brief  步进电机初始化
  * @param  *step_motor：步进电机结构体指针
  * @param  member_count：想要初始化的步进电机个数
	*	@note   无
  * @retval 无
  */
void stepper_Init(void)
{
    /*电机IO配置*/
    Stepper_GPIO_Config();
    /*定时器PWM输出配置*/
    TIM_PWMOUTPUT_Config();
    /*中断配置*/
    TIMx_NVIC_Configuration();
}

/**************插补相关算法****************/
Axis_TypeDef axis;
LinearInterpolation_TypeDef interpolation_para = {0};

/**
  * @brief  第一象限直线插补运动
  * @param  inc_x：终点坐标X的增量
  * @param  inc_y：终点坐标Y的增量
  * @param  speed：进给速度
  * @retval 无
  */
static void InterPolation_Move(uint32_t inc_x, uint32_t inc_y, uint16_t speed)
{
    /* 偏差清零 */
    interpolation_para.deviation = 0;

    /* 设置终点坐标 */
    interpolation_para.endpoint_x = inc_x;
    interpolation_para.endpoint_y = inc_y;
    /* 所需脉冲数为X、Y坐标增量之和 */
    interpolation_para.endpoint_pulse = inc_x + inc_y;

    /* 第一步进给的活动轴为X轴 */
    interpolation_para.active_axis = x_axis;
    /* 计算偏差 */
    interpolation_para.deviation -= interpolation_para.endpoint_y;

    /* 设置速度 */
    __HAL_TIM_SET_COMPARE(&TIM_StepperHandle, step_motor[x_axis].pul_channel, speed);
    __HAL_TIM_SET_COMPARE(&TIM_StepperHandle, step_motor[y_axis].pul_channel, speed);
    __HAL_TIM_SET_AUTORELOAD(&TIM_StepperHandle, speed * 2);

    /* 使能主输出 */
    __HAL_TIM_MOE_ENABLE(&TIM_StepperHandle);
    /* 开启X轴比较通道输出 */
    TIM_CCxChannelCmd(MOTOR_PUL_TIM, step_motor[interpolation_para.active_axis].pul_channel, TIM_CCx_ENABLE);
    HAL_TIM_Base_Start_IT(&TIM_StepperHandle);

    interpolation_para.motionstatus = 1;
}


/**
  * @brief  任意直线插补运动
  * @param  coordi_x：终点坐标X的增量
  * @param  coordi_y：终点坐标Y的增量
  * @param  speed：进给速度，定时器计数值
  * @retval 无
  */
void Linear_Interpolation(int32_t coordi_x, int32_t coordi_y, uint16_t speed)
{
    /* 判断当前是否正在做插补运动 */
    if(interpolation_para.motionstatus != 0)
        return;

    /* 判断坐标正负，以此决定各轴的运动方向 */
    if(coordi_x < 0)
    {
        interpolation_para.dir_x = CCW;
        coordi_x = -coordi_x;
        MOTOR_DIR(step_motor[x_axis].dir_port, step_motor[x_axis].dir_pin, CCW);
    }
    else
    {
        interpolation_para.dir_x = CW;
        MOTOR_DIR(step_motor[x_axis].dir_port, step_motor[x_axis].dir_pin, CW);
    }

    if(coordi_y < 0)
    {
        interpolation_para.dir_y = CCW;
        coordi_y = -coordi_y;
        MOTOR_DIR(step_motor[y_axis].dir_port, step_motor[y_axis].dir_pin, CCW);
    }
    else
    {
        interpolation_para.dir_y = CW;
        MOTOR_DIR(step_motor[y_axis].dir_port, step_motor[y_axis].dir_pin, CW);
    }

    /* 开始插补运动 */
    InterPolation_Move(coordi_x, coordi_y, speed);
}

/**
  * @brief  定时器比较中断回调函数
  * @param  htim：定时器句柄指针
	*	@note   无
  * @retval 无
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    uint32_t last_axis = 0;

    /* 记录上一步的进给活动轴 */
    last_axis = interpolation_para.active_axis;

    /* 根据上一步的偏差，判断的进给方向，并计算下一步的偏差 */
    if(interpolation_para.deviation >= 0)
    {
        /* 偏差>0，在直线上方，进给X轴，计算偏差 */
        interpolation_para.active_axis = x_axis;
        interpolation_para.deviation -= interpolation_para.endpoint_y;
    }
    else
    {
        /* 偏差<0，在直线下方，进给Y轴，计算偏差 */
        interpolation_para.active_axis = y_axis;
        interpolation_para.deviation += interpolation_para.endpoint_x;
    }

    /* 下一步的活动轴与上一步的不一致时，需要换轴 */
    if(last_axis != interpolation_para.active_axis)
    {
        TIM_CCxChannelCmd(htim->Instance, step_motor[last_axis].pul_channel, TIM_CCx_DISABLE);
        TIM_CCxChannelCmd(htim->Instance, step_motor[interpolation_para.active_axis].pul_channel, TIM_CCx_ENABLE);
    }

    /* 进给总步数减1 */
    interpolation_para.endpoint_pulse--;

    /* 判断是否完成插补 */
    if(interpolation_para.endpoint_pulse == 0)
    {
        /* 关闭定时器 */
        TIM_CCxChannelCmd(htim->Instance, step_motor[last_axis].pul_channel, TIM_CCx_DISABLE);
        TIM_CCxChannelCmd(htim->Instance, step_motor[interpolation_para.active_axis].pul_channel, TIM_CCx_DISABLE);
        __HAL_TIM_MOE_DISABLE(htim);
        HAL_TIM_Base_Stop_IT(htim);
        interpolation_para.motionstatus = 0;
    }
}


